package lion.framework.core.db;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import lion.dev.exception.DBException;
import lion.dev.lang.BeanUtil;
import lion.dev.lang.MapJ;
import lion.json.Json;




/**
 * 
 * 数据记录集,每行数据都是一个MapJ
 *
 * <pre>
 * time   2013 2013-4-24 上午11:27:36
 * mail   hl_0074@sina.com
 * </pre>
 *
 * @author lion
 */
public class DataTable {

	public static DataTable mapResult(ResultSet rs) {

		DataTable dt = new DataTable();
		dt.setResultSet(rs);

		return dt;
	}

	private List<MapJ> rows = new ArrayList<>();

	public DataTable() {

	}

	public DataTable(ResultSet rs) {

		setResultSet(rs);
	}

	public <T> T get(int row, int col) {

		MapJ mapJ = getRow(row);
		return mapJ.getE(col);
	}

	public <T> T get(int row, String col) {

		MapJ rowMap = getRow(row);

		return rowMap.getE(col);
	}

	public MapJ getRow(int row) {

		if (rows.size() < row) { return new MapJ(); }

		return rows.get(row);

	}

	public int getRowCount() {

		return rows.size();
	}

	public List<MapJ> getRows() {

		return rows;
	}

	public <T> List<T> list(Class<T> clazz) {

		List<T> result = new ArrayList<>();
		for (MapJ row : this.getRows()) {
			try {
				T t = clazz.newInstance();
				BeanUtil.populate(t, row);
				result.add(t);
			} catch (Exception e) {
			}
		}
		return result;
	}

	public void setResultSet(ResultSet rs) {

		try {
			ResultSetMetaData rsm = rs.getMetaData();

			String[] columns = new String[rsm.getColumnCount()];
			int[] types = new int[columns.length];
			for (int i = 0; i < columns.length; i++) {
				columns[i] = rsm.getColumnLabel(i + 1);
				types[i] = rsm.getColumnType(i + 1);
			}

			while (rs.next()) {

				MapJ row = new MapJ(); 

				for (int i = 0; i < columns.length; i++) {
					exractColumn(rs, columns[i], types[i], row, i + 1);
				}
				rows.add(row);
			}
		} catch (Exception e) {
			throw new DBException(e);
		}
	}

	public String toJSON() {

		return Json.toJson(rows);
	}

	private void exractColumn(ResultSet rs, String columnName, int sqltype, MapJ row, int i) throws SQLException {

		switch (sqltype) {
		case Types.BIT:
			row.put(columnName, rs.getBoolean(i));
			break;
		case Types.BLOB:
		case Types.BINARY:
		case Types.VARBINARY:
		case Types.LONGVARBINARY:
			row.put(columnName, rs.getBytes(i));
			break;
		case Types.CHAR:
		case Types.VARCHAR:
		case Types.LONGVARCHAR:
		case Types.CLOB:
		case Types.NCHAR:
		case Types.NVARCHAR:
		case Types.LONGNVARCHAR:
		case Types.NCLOB:
			row.put(columnName, rs.getString(i));
			break;
		case Types.SQLXML:
			row.put(columnName, rs.getSQLXML(i));
			break;
		case Types.TIME:
		case Types.DATE:
		case Types.TIMESTAMP:
			Timestamp ts = rs.getTimestamp(i);
			if (ts != null) {
				row.put(columnName, new Date(ts.getTime()));
			}
			break;
		default:
			row.put(columnName, rs.getObject(i));
		}
	}
}
